<template>
  <ConfigProvider :wave="{ disabled: true }">
    <div :class="{
      'theme-dark': theme === 'vs-dark',
      'theme-light': theme === 'vs-light',
      'theme-eyecare': theme === 'vs-eyecare'
    }">
      <Header
        :model="model"
        :theme="theme"
        :layout="layout"
        v-model:columnName="columnName"
        v-model:isCreateTable="isCreateTable"
        v-model:selectedMatelake="selectedMatelake"
        v-model:selectedCatalog="selectedCatalog"
        @themeChange="(newTheme: string) => (theme = newTheme)"
        @layoutChange="(newLayout: string) => (layout = newLayout)"
        @nodeSizeChange="(newTestSize: number) => (testSize = newTestSize)"
        @handleParseSql="handleParseSql"
        @modelChange="handleChangeModel"
        :highlightColor="highlightColor"
        :textWaterMarker="textWaterMarker"
        :showMinimap="showMinimap"
        @highlightColorChange="(newHighlightColor: string) => (highlightColor = newHighlightColor)"
        @textWaterMarkerChange="(newTextWaterMarker: string) => (textWaterMarker = newTextWaterMarker)"
        @dbTypeChange="(newDbType: string) => (selectedDbType = newDbType)"
        @update:showMinimap="(value: boolean) => (showMinimap = value)"
        @parseModeChange="(newMode: string) => (parseMode = newMode)"
      />
      <main class="flex-auto overflow-hidden border-t border-gray-200">
        <div class="splitPane">
          <div class="pane1" :style="{ width: isEditorCollapsed ? '40px' : `${editorWidth}px` }" ref="pane1">
            <!-- 添加收起/展开按钮 -->
            <div class="collapse-btn" @click="toggleEditorCollapse">
              <div class="collapse-icon">{{ isEditorCollapsed ? '›' : '‹' }}</div>
            </div>

            <div
  v-show="!isEditorCollapsed"
  class="flex flex-auto h-full"
  ref="ref1"
>
  <MonacoEditor
    ref="monacoEditorRef"
    :width="`${editorWidth - 10}px`"
    :height="'100%'"
    :language="'sql'"
    :theme="theme"
    v-model="code"
  />
</div>

            <!-- 添加拖拽条 -->
            <div
              v-show="!isEditorCollapsed"
              class="resize-handle"
              @mousedown="startResize"
            ></div>
          </div>
          <div class="pane2">
            <div
              class="relative w-full overflow-auto md:h-full"
              ref="ref2"
            >
              <Spin :spinning="loading">
                <template v-if="model === 'test'">
                  <LineageGraphTest
                    :layout="layout"
                    :lineageData="lineageData"
                    :highlightColor="highlightColor"
                    :textWaterMarker="textWaterMarker"
                  />
                </template>
                <template v-else>
                  <LineageGraph
                    :layout="layout"
                    :lineageData="lineageData"
                    v-model:nodeSize="nodeSize"
                    v-model:nodeLevel="nodeLevel"
                    @nodeLevel="(newNodeLevel: number) => (nodeLevel = newNodeLevel)"
                    :highlightColor="highlightColor"
                    :textWaterMarker="textWaterMarker"
                    :isEditorCollapsed="isEditorCollapsed"
                    :canvasWidth="canvasWidth"
                    v-model:showMinimap="showMinimap"
                    @selectNode="handleSelectNode"
                  />
                </template>
              </Spin>
            </div>
          </div>
          <!-- </SplitPane> -->
        </div>
      </main>
      <Footer
        :nodeSize="nodeSize"
        :nodeLevel="nodeLevel"
      />
      <!-- <ITour
        ref1="ref1"
        ref2="ref2"
      /> -->
      <div v-if="matches.length > 0" class="match-navigation">
  <div class="match-header">
    <span>匹配 {{ currentMatchIndex + 1 }} / {{ matches.length }}</span>
    <Button @click="closeMatchNavigation" size="small" class="close-btn">
      <span class="close-icon">×</span>
    </Button>
  </div>
  <div class="match-buttons">
    <Button @click="prevMatch" size="small">
      <span class="match-nav-icon">←</span> 上一个
    </Button>
    <Button @click="nextMatch" size="small">
      下一个 <span class="match-nav-icon">→</span>
    </Button>
  </div>
  <div class="match-shortcuts">
    快捷键: Alt+P (上一个) / Alt+N (下一个)
  </div>
</div>
    </div>
  </ConfigProvider>
</template>

<script lang="ts" setup>
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue';
import { Switch, Button } from 'ant-design-vue';
import * as monaco from 'monaco-editor';
import Header from '../components/Header/index.vue';
import Footer from '../components/Footer/index.vue';
import sourceData from '../test/data.json';
import MonacoEditor from '../components/MonacoEditor/index.vue';
import LineageGraph from '../components/LineageGraph/index.vue';
import LineageGraphTest from '../components/LineageGraphTest/index.vue';
import { getLineageData, getLineageDataFromMate } from '../services/api';
// import SplitPane from 'vue-splitpane';
import { message, Spin, ConfigProvider } from 'ant-design-vue';
import ITour from '../components/Tour/index.vue';
import { sql } from '../test/sql';
import { initData } from '../test/test';

const props = defineProps();
const columnName = ref(''); // 添加字段名输入框的值
const size = ref({
  percentage: 0.25,
  current: 340,
  min: 340,
  max: 0
});
const layout = ref('vertical');
const theme = ref('vs-light');

// 监听主题变化
watch(theme, (newTheme) => {
  let className = 'theme-light';
  if (newTheme === 'vs-dark') {
    className = 'theme-dark';
  } else if (newTheme === 'vs-eyecare') {
    className = 'theme-eyecare';
  }
  document.body.className = className;
});
const model = ref(import.meta.env.VITE_ENV);
const testSize = ref(0);
const selectedDbType = ref('');
const parseMode = ref('createTable'); // 默认为解析建表语句
const selectedMatelake = ref('');
const selectedCatalog = ref('');
// 保存默认SQL作为初始值
const defaultSql = sql();
const code = ref(defaultSql);
const monacoEditorRef = ref(null);
const loading = ref(false);
const lineageData = ref<any>({});
const highlightColor = ref('red');
const textWaterMarker = ref('');  // 修改这里为您想要的水印文字
const showMinimap = ref(false); // 控制缩略图显示
const isCreateTable = ref(false); // 控制是否为创建表操作
const ref1 = ref(null);
const ref2 = ref(null);
const nodeSize = ref(0);
const nodeLevel = ref(0);
// 添加画布宽度计算
const canvasWidth = ref(0);

// 添加匹配相关的变量
const matches = ref([]);
const currentMatchIndex = ref(0);

// 编辑器宽度和折叠状态
const editorWidth = ref(340);
const isEditorCollapsed = ref(false);
const minEditorWidth = 200;
const maxEditorWidth = ref(Math.floor(document.documentElement.clientWidth * 0.8)); // 设置为页面宽度的80%

const splitPaneProps = {
  split: 'vertical',
  minSize: size.value.min,
  maxSize: size.value.max,
  size: size.value.current,
  // onChange: (newSize: any) => console.log(newSize),
  // onDragStarted: () => console.log('拖动开始'),
  // onDragFinished: () => console.log('拖动结束'),
  // allowResize: false,
};

const handleParseSql = () => {
  // 更新code值为当前输入框的内容（不需要额外操作，因为v-model已经自动同步）
  if (model.value === 'test') {
    nodeSize.value = testSize.value;
    nodeLevel.value = testSize.value;

    lineageData.value = initData(testSize.value);
    console.log(
      '🚀 ~ file: index.vue:123 ~ handleParseSql ~ lineageData.value:',
      lineageData.value
    );
    return;
  }

  // 检查输入
  if (!code.value) {
    message.error('请输入SQL语句');
    return;
  }

  // 检查数据库类型（仅在非外部元数据模式下）
  if (parseMode.value !== 'external' && !selectedDbType.value) {
    message.error('请选择数据库类型');
    return;
  }

  // 检查外部元数据选择（仅在外部元数据模式下）
  if (parseMode.value === 'external' && (!selectedMatelake.value || !selectedCatalog.value)) {
    message.error('请选择Matelake和Catalog');
    return;
  }

  loading.value = true;

  // 根据解析模式选择不同的API调用
  const apiPromise = parseMode.value === 'external' 
    ? getLineageDataFromMate(selectedMatelake.value, selectedCatalog.value, code.value, columnName.value || undefined)
    : getLineageData(
        selectedDbType.value || 'hive', 
        code.value, 
        columnName.value || undefined, 
        parseMode.value === 'createTable'
      );

  apiPromise
    .then((response: any) => {
      if (response && (response.code === 0 || response.code === 200)) {
        lineageData.value = response.data || {};
        if (lineageData.value.withProcessData && lineageData.value.withProcessData.size) {
          nodeSize.value = lineageData.value.withProcessData.size;
          nodeLevel.value = lineageData.value.withProcessData.level || 0;
        }
        // 移除成功提示
      } else {
        throw new Error(response?.message || '未知错误');
      }
    })
    .catch((e: any) => {
      console.error('API 错误:', e);
      message.error('处理异常！' + (e.message || e));
    })
    .finally(() => {
      loading.value = false;
    });
  // 更新大小
  updateSize();
}

const updateSize = () => {
  const isPreview = layout.value === 'preview';
  size.value.current = isPreview ? 0 : editorWidth.value;
  size.value.min = isPreview ? 0 : minEditorWidth;
  // 使用动态计算的最大宽度
  size.value.max = isPreview ? 0 : maxEditorWidth.value;
};

// 处理编辑器折叠/展开
const toggleEditorCollapse = () => {
  isEditorCollapsed.value = !isEditorCollapsed.value;
  // 如果是从折叠状态展开，恢复之前的宽度
  if (!isEditorCollapsed.value && editorWidth.value < minEditorWidth) {
    editorWidth.value = 340;
  }
  // 更新画布宽度
  calculateCanvasWidth();
};

// 计算画布宽度
const calculateCanvasWidth = () => {
  // 获取窗口总宽度
  const windowWidth = document.documentElement.clientWidth;
  // 根据编辑器是否折叠计算画布宽度
  canvasWidth.value = windowWidth - (isEditorCollapsed.value ? 40 : editorWidth.value);
};

// 处理拖拽调整宽度
const pane1 = ref(null);
const startResize = (e) => {
  e.preventDefault();

  const startX = e.clientX;
  const startWidth = pane1.value.offsetWidth;

  const handleMouseMove = (moveEvent) => {
    moveEvent.preventDefault();
    const deltaX = moveEvent.clientX - startX;
    // 使用 maxEditorWidth.value 来获取响应式的最大宽度值
    const newWidth = Math.max(minEditorWidth, Math.min(maxEditorWidth.value, startWidth + deltaX));
    editorWidth.value = newWidth;
    if (pane1.value) {
      pane1.value.style.width = `${newWidth}px`;
    }
    // 更新画布宽度
    calculateCanvasWidth();
  };

  const handleMouseUp = () => {
    document.removeEventListener('mousemove', handleMouseMove);
    document.removeEventListener('mouseup', handleMouseUp);
  };

  document.addEventListener('mousemove', handleMouseMove, { passive: false });
  document.addEventListener('mouseup', handleMouseUp, { passive: true });
};

onMounted(() => {
  // 初始化时设置最大宽度为页面宽度的80%
  maxEditorWidth.value = Math.floor(document.documentElement.clientWidth * 0.8);
  updateSize();
  // 初始化画布宽度
  calculateCanvasWidth();

  window.addEventListener('resize', () => {
    // 更新编辑器最大宽度
    maxEditorWidth.value = Math.floor(document.documentElement.clientWidth * 0.8);
    updateSize();
    // 更新画布宽度
    calculateCanvasWidth();
  });
});

onUnmounted(() => {
  window.removeEventListener('resize', updateSize);
});

const handleChangeModel = (newModel: string) => {
  model.value = newModel;
  lineageData.value = null;
  nodeSize.value = 0;
  nodeLevel.value = 0;
  testSize.value = 0;
};

const handleSelectNode = ({ tableName, fieldName }) => {
  let bestMatchLineIndex = -1;
  let bestMatchColumnIndex = -1;
  let fieldLineIndex = -1;
  let fieldColumnIndex = -1;
  let tableLineIndex = -1;
  let tableColumnIndex = -1;

  if (!tableName && !fieldName) return;

  // 在SQL中查找表名和字段名
  const searchText = fieldName || tableName;
  const fieldRegex = fieldName ? new RegExp(`\\b${escapeRegExp(fieldName)}\\b`, 'gi') : null;
  const tableRegex = tableName ? new RegExp(`\\b${escapeRegExp(tableName)}\\b`, 'gi') : null;

  const regex = new RegExp(`\\b${escapeRegExp(searchText)}\\b`, 'gi');

  const lines = code.value.split('\n');
  matches.value = [];

  // 首先查找精确匹配
  for (let i = 0; i < lines.length; i++) {
    const line = lines[i];
    let match;
    while ((match = regex.exec(line)) !== null) {
      // 确保匹配的是完整的单词
      const prevChar = line[match.index - 1] || ' ';
      const nextChar = line[match.index + searchText.length] || ' ';
      const isWordBoundary = /\W/.test(prevChar) && /\W/.test(nextChar);

      if (isWordBoundary) {
        matches.value.push({
          lineNumber: i + 1,
          startColumn: match.index + 1,
          endColumn: match.index + searchText.length + 1,
          text: searchText
        });
      }
    }
  }

  // 如果没有找到匹配，尝试不区分大小写的搜索
  if (matches.value.length === 0) {
    const caseInsensitiveRegex = new RegExp(escapeRegExp(searchText), 'gi');
    for (let i = 0; i < lines.length; i++) {
      const line = lines[i];
      let match;
      while ((match = caseInsensitiveRegex.exec(line)) !== null) {
        matches.value.push({
          lineNumber: i + 1,
          startColumn: match.index + 1,
          endColumn: match.index + match[0].length + 1,
          text: match[0]
        });
      }
    }
  }

  if (matches.value.length > 0) {
    // message.info(`找到 ${matches.value.length} 个匹配项`);
    currentMatchIndex.value = 0;
    highlightCurrentMatch();

    // 获取第一个匹配项的位置
    const firstMatch = matches.value[0];
    bestMatchLineIndex = firstMatch.lineNumber - 1;
    bestMatchColumnIndex = firstMatch.startColumn - 1;

    // 如果找到了匹配位置，就定位到相应位置
    nextTick(() => {
      if (monacoEditorRef.value) {
        const editor = monacoEditorRef.value.getEditor();
        if (bestMatchLineIndex !== -1) {
          // 展开编辑器（如果已折叠）
          if (isEditorCollapsed.value) {
            toggleEditorCollapse();
          }

          // 定位到匹配位置并高亮
          editor.revealPositionInCenter({
            lineNumber: firstMatch.lineNumber,
            column: firstMatch.startColumn
          });

          // 设置光标位置
          editor.setPosition({
            lineNumber: firstMatch.lineNumber,
            column: firstMatch.startColumn
          });

          // 选中匹配的文本
          editor.setSelection({
            startLineNumber: firstMatch.lineNumber,
            startColumn: firstMatch.startColumn,
            endLineNumber: firstMatch.lineNumber,
            endColumn: firstMatch.endColumn
          });

          editor.focus();
        }
      }
    });
  } else {
    message.warning(`未找到 "${searchText}" 的匹配项`);
  }
};

// 高亮当前匹配项
const highlightCurrentMatch = () => {
  if (matches.value.length === 0) return;

  nextTick(() => {
    if (monacoEditorRef.value) {
      const editor = monacoEditorRef.value.getEditor();
      const match = matches.value[currentMatchIndex.value];

      // 展开编辑器（如果已折叠）
      if (isEditorCollapsed.value) {
        toggleEditorCollapse();
      }

      // 定位到匹配位置
      editor.revealPositionInCenter({
        lineNumber: match.lineNumber,
        column: match.startColumn
      });

      // 选中匹配的文本
      editor.setSelection({
        startLineNumber: match.lineNumber,
        startColumn: match.startColumn,
        endLineNumber: match.lineNumber,
        endColumn: match.endColumn
      });

      editor.focus();
    }
  });
};

// 导航到下一个匹配项
const nextMatch = () => {
  if (matches.value.length === 0) return;
  currentMatchIndex.value = (currentMatchIndex.value + 1) % matches.value.length;
  highlightCurrentMatch();
};

// 导航到上一个匹配项
const prevMatch = () => {
  if (matches.value.length === 0) return;
  currentMatchIndex.value = (currentMatchIndex.value - 1 + matches.value.length) % matches.value.length;
  highlightCurrentMatch();
};

// 关闭匹配导航
const closeMatchNavigation = () => {
  matches.value = [];
  currentMatchIndex.value = 0;
  // 清除编辑器中的高亮
  if (monacoEditorRef.value) {
    const editor = monacoEditorRef.value.getEditor();
    editor.setSelection({
      startLineNumber: 1,
      startColumn: 1,
      endLineNumber: 1,
      endColumn: 1
    });
  }
};

// 添加键盘快捷键
onMounted(() => {
  // 初始化时设置最大宽度为页面宽度的80%
  maxEditorWidth.value = Math.floor(document.documentElement.clientWidth * 0.8);
  updateSize();
  // 初始化画布宽度
  calculateCanvasWidth();

  window.addEventListener('resize', () => {
    // 更新编辑器最大宽度
    maxEditorWidth.value = Math.floor(document.documentElement.clientWidth * 0.8);
    updateSize();
    // 更新画布宽度
    calculateCanvasWidth();
  });

  // 添加键盘事件监听器
  window.addEventListener('keydown', (e) => {
    if (e.altKey && e.key === 'n') {
      e.preventDefault();
      nextMatch();
    } else if (e.altKey && e.key === 'p') {
      e.preventDefault();
      prevMatch();
    }
  });
});

onUnmounted(() => {
  window.removeEventListener('resize', updateSize);
  window.removeEventListener('keydown', (e) => {
    if ((e.altKey && e.key === 'n') || (e.altKey && e.key === 'p')) {
      e.preventDefault();
    }
  });
});

// 辅助函数：转义正则表达式特殊字符
function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
</script>

<style scoped>
.splitPane {
  display: flex;
  flex: 1 1 0%;
  height: 100%;
  position: absolute;
  outline: none;
  overflow: hidden;
  user-select: text;
  flex-direction: row;
  left: 0px;
  right: 0px;
  transition: background-color 0.3s;
}

.pane1 {
  flex: 0 0 auto;
  position: relative;
  outline: none;
  height: calc(100vh - 100px); /* 减去头部和底部的高度 */
  overflow: hidden;
  transition: width 0.3s ease;
  display: flex;
  align-items: stretch;
}

.pane2 {
  flex: 1 1 0%;
  position: relative;
  outline: none;
}

/* 拖拽条样式 */
.resize-handle {
  width: 8px;
  height: calc(100vh - 100px);
  cursor: col-resize;
  background-color: #f0f0f0;
  transition: background-color 0.2s;
  z-index: 100;
  position: absolute;
  right: -4px;
  top: 0;
}

.resize-handle:hover {
  background-color: #ddd;
}

/* 收起/展开按钮样式 */
.collapse-btn {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 20px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: #f0f0f0;
  cursor: pointer;
  z-index: 11;
  border-radius: 4px 0 0 4px;
  transition: background-color 0.2s;
}

.collapse-btn:hover {
  background-color: #ddd;
}

.collapse-icon {
  font-size: 18px;
  font-weight: bold;
}

/* 匹配导航样式 */
.match-navigation {
  position: fixed;
  bottom: 80px;  /* 调整位置，避免与其他元素重叠 */
  right: 20px;
  background-color: var(--ant-primary-1);
  padding: 12px;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
  z-index: 1000;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  font-size: 14px;
  border: 1px solid var(--ant-primary-3);
  min-width: 240px;
}

.match-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  margin-bottom: 8px;
}

.match-navigation span {
  color: var(--ant-text-color);
  font-weight: 500;
}

.close-btn {
  padding: 0 6px;
  height: 24px;
  min-width: 24px;
  font-size: 14px;
  line-height: 24px;
}

.close-icon {
  font-weight: bold;
}

.match-buttons {
  display: flex;
  gap: 8px;
  width: 100%;
}

.match-buttons .ant-btn {
  flex: 1;
  height: 32px;
  padding: 0 12px;
  font-size: 14px;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.match-nav-icon {
  font-size: 16px;
  line-height: 1;
}

.match-shortcuts {
  font-size: 12px;
  color: var(--ant-text-color-secondary);
  margin-top: 4px;
}

.theme-dark .match-shortcuts {
  color: rgba(255, 255, 255, 0.45);
}

.theme-eyecare .match-shortcuts {
  color: rgba(0, 0, 0, 0.45);
}

.theme-dark .match-navigation {
  background-color: rgba(45, 45, 45, 0.95);
  border-color: rgba(255, 255, 255, 0.15);
}

.theme-dark .match-navigation span {
  color: rgba(255, 255, 255, 0.85);
}

.theme-eyecare .match-navigation {
  background-color: rgba(242, 234, 212, 0.95);
  border-color: rgba(0, 0, 0, 0.1);
}

.theme-eyecare .match-navigation span {
  color: rgba(0, 0, 0, 0.85);
}

/* 确保两个按钮样式一致 */
.match-buttons .ant-btn {
  background-color: #ffffff;
  border-color: #d9d9d9;
  color: rgba(0, 0, 0, 0.85);
}

.theme-dark .match-buttons .ant-btn {
  background-color: #1f1f1f;
  border-color: #434343;
  color: rgba(255, 255, 255, 0.85);
}

.theme-eyecare .match-buttons .ant-btn {
  background-color: #f2ead4;
  border-color: #d3c17a;
  color: rgba(0, 0, 0, 0.85);
}

/* 按钮悬停效果 */
.match-buttons .ant-btn:hover {
  background-color: #f0f0f0;
  border-color: #40a9ff;
  color: #40a9ff;
}

.theme-dark .match-buttons .ant-btn:hover {
  background-color: #2a2a2a;
  border-color: #177ddc;
  color: #177ddc;
}

.theme-eyecare .match-buttons .ant-btn:hover {
  background-color: #e8e0c5;
  border-color: #52c41a;
}
</style>
